package otw.dao.mongo;

import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import otw.utils.properties.PropertiesUtil;

import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;

/**
 * <p>
 * Mongo connection util, use <b>singleton</b> pattern.
 * </p>
 * 
 * @author eric
 * @date Dec 15, 2012 12:05:38 AM
 */
public final class MongoConn {
	protected Logger logger = Logger.getLogger(MongoConn.class);

	public static final String defaultConfigFilePath = "mongo/mongo.properties";
	public static final int defaultPoolSize = 10;
	public static final int defaultQueueSize = 5;

	private String configFilePath; // classpath of mongo config file, in format "xx/xx/xx.properties",
	private Properties prop;
	private String db; // default db
	private String mongoUser;
	private String mongoPassword;
	private int poolSize; // connection pool size
	private int queueSize; // queue size for each connection
	private Mongo mongo;

	private static final MongoConn defaultConn = new MongoConn(defaultConfigFilePath); // singleton instance

	private MongoConn(String configFilePath) {
		this.configFilePath = configFilePath;
		initMongo();
	}

	/**
	 * init Mongo
	 */
	private void initMongo() {
		try {
			prop = PropertiesUtil.load(configFilePath);
			db = prop.getProperty("db");
			mongoUser = prop.getProperty("user");
			mongoPassword = prop.getProperty("password");

			String poolSizeStr = prop.getProperty("pool_size");
			poolSize = StringUtils.isBlank(poolSizeStr) ? defaultPoolSize : Integer.parseInt(poolSizeStr);
			String queueSizeStr = prop.getProperty("queue_size");
			queueSize = StringUtils.isBlank(queueSizeStr) ? defaultQueueSize : Integer.parseInt(queueSizeStr);

			// specify mongo server
			mongo = new Mongo(prop.getProperty("host"), Integer.parseInt(prop.getProperty("port")));

			// set mongo option
			MongoOptions opt = mongo.getMongoOptions();
			opt.connectionsPerHost = poolSize;
			opt.threadsAllowedToBlockForConnectionMultiplier = queueSize;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static MongoConn getDefaultConn() {
		return defaultConn;
	}

	/**
	 * get default db
	 * 
	 * @return
	 */
	public DB getDB() {
		return getDB(db);
	}

	/**
	 * get db by name
	 * 
	 * @param dbName
	 * @return
	 */
	public DB getDB(String dbName) {
		return mongo.getDB(db);
	}

	/**
	 * get default db with auth
	 * 
	 * @return
	 */
	public DB getDBAuth() {
		return getDBAuth(db, mongoUser, mongoPassword);
	}

	/**
	 * get db by name with auth
	 * 
	 * @param dbName
	 * @param user
	 * @param password
	 * @return
	 */
	public DB getDBAuth(String dbName, String user, String password) {
		// connect to a db,
		DB db = mongo.getDB(dbName);
		// auth
		if (!db.isAuthenticated()) {
			boolean auth = db.authenticate(user, password.toCharArray());
			if (!auth) {
				logger.error("db auth fail!");
			} else {
				logger.info("db auth success!");
			}
		}
		return db;
	}
}
